package api

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"math/rand"
	"net/http"
	"strings"
	"time"
	"web_end/forms"
	"web_end/global"
	"web_end/global/response"
)

// GenerateSmsCode /* 生成width长度的短信验证码
func GenerateSmsCode(width int) string {
	numeric := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	r := len(numeric)
	rand.Seed(time.Now().UnixNano())

	var sb strings.Builder
	for i := 0; i < width; i++ {
		_, _ = fmt.Fprintf(&sb, "%d", numeric[rand.Intn(r)])
	}
	return sb.String()
}

// SendSms /* 短信服务
func SendSms(ctx *gin.Context) {
	sendSmsForm := forms.SendSmsForm{}
	if err := ctx.ShouldBind(&sendSmsForm); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"msg":  "参数错误",
			"code": response.CodeBadRequest,
		})
		return
	}

	client, err := sdk.NewClientWithAccessKey("cn-chengdu", global.ServerConfig.AliSmsInfo.ApiKey, global.ServerConfig.AliSmsInfo.ApiSecret)

	code := GenerateSmsCode(6)

	request := requests.NewCommonRequest()                           // 构造一个公共请求
	request.Method = "POST"                                          // 设置请求方式
	request.Product = "Ecs"                                          // 指定产品
	request.Scheme = "https"                                         // https | http
	request.Domain = "dysmsapi.aliyuncs.com"                         // 指定域名则不会寻址，如认证方式为 Bearer Token 的服务则需要指定
	request.Version = "2017-05-25"                                   // 指定产品版本
	request.ApiName = "SendSms"                                      // 指定接口名
	request.QueryParams["RegionId"] = "cn-chengdu"                   // 地区
	request.QueryParams["PhoneNumbers"] = sendSmsForm.Mobile         //手机号
	request.QueryParams["SignName"] = "小橡木"                          //阿里云验证过的项目名 自己设置
	request.QueryParams["TemplateCode"] = "SMS_268686025"            //阿里云的短信模板号 自己设置
	request.QueryParams["TemplateParam"] = "{\"code\":" + code + "}" //短信模板中的验证码内容 自己生成

	smsResponse, err := client.ProcessCommonRequest(request)
	if err != nil {
		zap.S().Errorf("发送短信验证码失败: %s", err.Error())
		ctx.JSON(http.StatusOK, gin.H{
			"code": response.CodeInternalServerError,
			"msg":  "发送短信验证码失败",
		})
		return
	}
	var message Message // 阿里云返回的json信息对应的类
	// 判断错误信息
	_ = json.Unmarshal(smsResponse.GetHttpContentBytes(), &message)
	if message.Message != "OK" {
		zap.S().Errorw("发送短信验证码失败: ", message.Message)
		ctx.JSON(http.StatusOK, gin.H{
			"code": response.CodeInternalServerError,
			"msg":  "发送短信验证码失败",
		})
		return
	}

	smsPhone := fmt.Sprintf("sms:phone:%s", sendSmsForm.Mobile)
	global.Rd.Set(context.Background(), smsPhone, code, time.Duration(global.ServerConfig.RedisInfo.Expired)*time.Second)

	ctx.JSON(http.StatusOK, gin.H{
		"code": response.CodeOk,
		"msg":  "发送短信验证码成功",
	})
}

// Message /* json数据解析
type Message struct {
	Message   string
	RequestId string
	BizId     string
	Code      string
}
